package com.colabo.j2ee.web.core.log;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.core.Ordered;

import com.colabo.j2ee.web.core.common.CommonConstants;
import com.colabo.j2ee.web.core.util.PropertyUtil;

/**
 * 用于Spring的AOP方式的log4j日志记录管理器<br>
 * 
 * 不建议使用aspect方式插入，请用本目录下以xxxAdvise.java的方式代替 
 * 使用方法：<br>
 * vbean id="logAspect" class="com.cib.cap.base.common.log.LogAspect"/&gt;<br>
 * &lt;aop:config&gt; <br>
 * &lt;aop:pointcut id="loggingPointCut" expression="execution(public com.cib.cap..*Service.*(..))"/&gt; <br>
 * &lt;aop:aspect ref="logAspect"&gt;<br>
 * 		vaop:before pointcut-ref="loggingPointCut" method="beforeLog"/&gt;<br>
 * 		&lt;aop:after-returning pointcut-ref="loggingPointCut" method="afterLog"/&gt;<br>
 * 		&lt;aop:after-throwing pointcut-ref="loggingPointCut" throwing="ex" method="exceptionLog"/&gt; <br>
 * &lt;/aop:aspect&gt; <br>
 * &lt;/aop:config&gt;<br>
 */
public class LogAspect implements Ordered {
	protected final Log logger = LogFactory.getLog(LogAspect.class);
	private int order = 1;

	public int getOrder() {
		return order;
	}

	public void setOrder(int order) {
		this.order = order;
	}

	public void exceptionLog(JoinPoint jp, Throwable ex) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < ex.getStackTrace().length; i++) {
			StackTraceElement ste = (StackTraceElement) ex.getStackTrace()[i];
			sb.append(ste.toString() + "\n");
		}
		logger.info(PropertyUtil.getPropertyByKey(CommonConstants.MSG_LOG_EXCEPTION, new String[] {
				jp.getTarget().getClass().getName(), jp.getSignature().getName(), ex.toString(), sb.toString() }));
		logger.error("日志拦截: 非正常退出 [" + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName()
				+ "] 抛出的异常为：" + ex + " \n 异常堆栈信息如下：\n" + sb.toString());
	}

	public void beforeLog(ProceedingJoinPoint jp) throws Throwable {
		// 解析参数
		Object[] params = jp.getArgs();
		StringBuffer sb = new StringBuffer("");
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				if (params[i] != null) {
					sb.append(params[i].toString());
					sb.append(",");
				}
			}
		} else {
			sb.append("无输入参数");
		}

		logger.info(PropertyUtil.getPropertyByKey(CommonConstants.MSG_LOG_BEFORE, new String[] {
				jp.getTarget().getClass().getName(), jp.getSignature().getName(), sb.toString() }));
	}

	public Object afterLog(ProceedingJoinPoint jp) throws Throwable {
		// 解析返回值
		Object rtvar = jp.proceed();
		logger.info(PropertyUtil.getPropertyByKey(CommonConstants.MSG_LOG_AFTER, new String[] {
				jp.getTarget().getClass().getName(), jp.getSignature().getName(),
				rtvar != null ? rtvar.toString() : "null" }));
		return rtvar;
	}

	public Object aroundLog(ProceedingJoinPoint jp) throws Throwable {
		long procTime = System.currentTimeMillis();
		// 解析参数
		Object[] params = jp.getArgs();
		StringBuffer sb = new StringBuffer("");
		for (int i = 0; i < params.length; i++) {
			sb.append(params[i].toString());
			sb.append(",");
		}
		logger.info(PropertyUtil.getPropertyByKey(CommonConstants.MSG_LOG_BEFORE, new String[] {
				jp.getTarget().getClass().getName(), jp.getSignature().getName(), sb.toString() }));

		try {
			Object result = jp.proceed();
			return result;
		} finally {
			// 计算执行时间
			procTime = System.currentTimeMillis() - procTime;
			logger.info(PropertyUtil.getPropertyByKey(CommonConstants.MSG_LOG_AFTER, new String[] {
					jp.getTarget().getClass().getName(), jp.getSignature().getName(), jp.proceed().toString() }));
			logger.info(PropertyUtil.getPropertyByKey(CommonConstants.MSG_LOG_AFTER, new String[] {
					jp.getTarget().getClass().getName(), jp.getSignature().getName(), String.valueOf(procTime) }));
		}
	}
}
